#ifndef _UART_PACKET_H_
#define _UART_PACKET_H_

#include <stdint.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdarg.h>
#include "aos/hal/uart.h"


#define USER_NAME_SIZE   32
#define VERSION_INFO_BUFFER_SIZE 32
#define DATA_RECVED_MAX_NUM 50
#define MAX_USER_COUNTS  20
#define H2M_PACKET_MAGIC_LEN 2
#define H2M_PACKET_HEADER_LEN 5
#define H2M_PACKET_HEADER_TOTAL_LEN (H2M_PACKET_MAGIC_LEN + H2M_PACKET_HEADER_LEN)

/* msg face direction */
typedef uint8_t s_face_dir;
#define FACE_DIRECTION_ALL   	 0x1F       // face all
#define FACE_DIRECTION_UP   	 0x10       // face up
#define FACE_DIRECTION_DOWN      0x08       // face down
#define FACE_DIRECTION_LEFT      0x04       // face left
#define FACE_DIRECTION_RIGHT     0x02       // face right
#define FACE_DIRECTION_MIDDLE    0x01       // face middle
#define FACE_DIRECTION_UNDEFINE  0x00       // face undefine

#define FACE_DIRECTION_NUM_MAX  0x05       // face direction num

#define SYNC_WORD                               (0xEFAA)
#define SYNC_WORD_FIRST                         ((SYNC_WORD&0x0000FF00)>>8 )
#define SYNC_WORD_SECOND                        ((SYNC_WORD&0x000000FF)>>0 )

#define MSG_REPLY_HEAD_SIZE   (7)

typedef enum _PACK_MID_E
{
	MID_REPLY=0x00,
	MID_NOTE=0x01,
	MID_IMAGE=0x02,
	MID_RESET=0x10,
	MID_GETSTATUS=0x11,
	MID_VERIFY=0x12,
	MID_ENROLL=0x13,
    MID_ENROLL_UART=0x14,
    MID_SAVE_FEARURE_UART=0x15,
	MID_SNAPIMAGE=0x16,
	MID_GETSAVEDIMAGE=0x17,
	MID_UPLOADIMAGE=0x18,
	MID_DELUSER=0x20,
	MID_DELALL=0x21,
	MID_GETUSERINFO=0x22,
	MID_FACERESET=0x23,
	MID_GETALLUSERID=0x24,
    DRAW_RECT=0x24,
	MID_ENROLL_COVER=0x25,
	MID_DELUSER_RANG=0x26,
    MID_GET_MODLE_VERSION=0x27,
	MID_GET_VERSION=0x30,
    MID_WRITE_SN = 0x31,      // write sn to board
	MID_START_OTA=0x40,
	MID_STOP_OTA=0x41,
	MID_GET_OTA_STATUS=0x42,
	MID_OTA_HEADER=0x43,
	MID_OTA_PACKET=0x44,
	MID_INIT_ENCRYPTION=0x50,
	MID_CONFIG_BAUDRATE=0x51,
	MID_SET_RELEASE_ENC_KEY=0x52,
	MID_SET_DEBUG_ENC_KEY=0x53,
	MID_GET_LOGFILE=0x60,
	MID_UPLOAD_LOGFILE=0x61,
	MID_ISP_START_SET = 0x71,
	MID_ISP_STOP_SET = 0x72,
	MID_RECT_COLOUR_SET = 0x73,
    MID_FACTORY_TEST = 0xC0, // factory test
    MID_CONTINUE_RECOGNIZE = 0xC1, 
	MID_SET_THRESHOLD_LEVEL=0xD4,
	MID_POWERDOWN=0xED,
	MID_DEBUG_MODE=0xF0,
	MID_GET_DEBUG_INFO=0xF1,
	MID_UPLOAD_DEBUG_INFO=0xF2,
	MID_DEMOMODE=0xFE,

    MI2_PC2MCU_REQUEST_ID = 0xB0,
    MI2_PC2MCU_REQUEST_ID_ACK = 0xB1,
    MI2_PC2MCU_REQUEST_ALL_ID = 0xB2,
    MI2_PC2MCU_REQUEST_ALL_ID_ACK = 0xB3,

    MI2_PC2MCU_CHILD_CURRENT_ID = 0xB2,
    MI2_PC2MCU_CHILD_ALL_ID = 0xB3,

    MID_NOTIFY_COULD_BROKE_PEEPHOLE = 0xA0,

    MID_MAX = 0xFF,
}MsgID_e;

typedef enum _PACK_MSG_ERRCODE_E
{
    MR_SUCCESS    = 0,     // success
    MR_REJECTED   = 1,     // module rejected this command
    MR_ABORTED    = 2,     // algo aborted
    MR_FAILED4_CAMERA = 4, // camera open failed
    MR_FAILED4_UNKNOWNREASON = 5, // UNKNOWN_ERROR
    MR_FAILED4_INVALIDPARAM = 6,  // invalid param
    MR_FAILED4_NOMEMORY = 7,      // no enough memory
    MR_FAILED4_UNKNOWNUSER = 8,   // no user enrolled
    MR_FAILED4_MAXUSER = 9,       // exceed maximum user number
    MR_FAILED4_FACEENROLLED = 10, // this face has been enrolled
    MR_FAILED4_LIVENESSCHECK = 12,// liveness check failed
    MR_FAILED4_TIMEOUT = 13,      // exceed the time limit
    MR_FAILED4_AUTHORIZATION = 14,// authorization failed
    MR_FAILED4_CAMERAFOV = 15,    // camera fov test failed
    MR_FAILED4_CAMERAQUA = 16,    // camera quality test failed
    MR_FAILED4_CAMERASTRU = 17,   // camera structure test failed
    MR_FAILED4_BOOT_TIMEOUT = 18, // boot up timeout
    MR_FAILED4_READ_FILE = 19,    // read file failed
    MR_FAILED4_WRITE_FILE = 20,   // write file failed
    MR_FAILED4_NO_ENCRYPT = 21,   // encrypt must be set
    MR_FAILED4_NO_RGBIMAGE= 23,   // rgb image is not ready
}MsgErrCode_e;

typedef enum _PACK_MSG_STATE_E
{
    MS_STANDBY = 0, // IDLE, waiting for commands
    MS_BUSY = 1,    // in working of processing commands
    MS_ERROR = 2,   // in error state. can't work properly
    MS_INVALID = 3, // not initialized
    MS_OTA = 4,     // in ota state

}MsgState_e;

typedef enum _PACK_MSG_NOTE_E
{
    NID_READY = 0,        // module ready for handling request (command)
    NID_FACE_STATE = 1,   // the detected face status description
    NID_UNKNOWNERROR = 2, // unknown error
    NID_OTA_DONE = 3,     // OTA upgrading processing done
}MsgNote_e;

typedef enum _PACK_FACE_STATE_E
{
	FACE_STATE_NORMAL     = 0, 	// normal state, the face is available
	FACE_STATE_NOFACE     = 1, 	// noface detected
	FACE_STATE_TOOUP      = 2,  // face is too up side
	FACE_STATE_TOODOWN    = 3,  // face is too down side
	FACE_STATE_TOOLEFT    = 4,  // face is too left side
	FACE_STATE_TOORIGHT   = 5,  // face is too right side
	FACE_STATE_TOOFAR     = 6,  // face is too far
	FACE_STATE_TOOCLOSE   = 7,  // face is too near
	FACE_STATE_EYEBROW_OCCLUSION = 8,   // eyebrow occlusion
	FACE_STATE_EYE_OCCLUSION     = 9,   // eye occlusion
	FACE_STATE_FACE_OCCLUSION    = 10,  // face occlusion
	FACE_STATE_DIRECTION_ERROR   = 11,  // face direction error
	FACE_STATE_EYE_CLOSE_STATUS_OPEN_EYE = 12,  // eye close time out
	FACE_STATE_EYE_CLOSE_STATUS          = 13,  // confirm eye close status
	FACE_STATE_EYE_CLOSE_UNKNOW_STATUS   = 14,  // eye close unknow status
}FaceState_e;

typedef enum _PACK_THRESH_LEVEL_E
{
    THRESHOLD_LEVEL_LOW    		= 0,
	THRESHOLD_LEVEL_LOWER    	= 1,
	THRESHOLD_LEVEL_NORMAL    	= 2,
	THRESHOLD_LEVEL_HIGHER    	= 3,
	THRESHOLD_LEVEL_HIGH    	= 4,
}thresh_level_e;

typedef enum _PACK_DEL_USER_FLAG_E
{
    FLAG_DEL_USER_NORMAL = 0, 
    FLAG_DEL_USER_RANGE = 1, 
}DelUserFlag_e;


//msg reply 
typedef struct {
    uint8_t sync_word[2];
    uint8_t cmd;
    uint8_t size[2];  // high eight bits
} s_msg_reply_head;

typedef struct {
    uint8_t nid;    // note id
    uint8_t  result;
    uint8_t data[64];
} s_msg_reply_data;

typedef struct {
    s_msg_reply_head msg_reply_head;
    s_msg_reply_data msg_reply_data;
} s_msg_reply;

typedef struct {
    uint8_t sync_word[2];
    uint8_t size[2];  // high eight bits
} s_msg_enc_reply_head;

typedef struct {
 
    uint8_t data[64];
} s_msg_enc_reply_data;

typedef struct {
    s_msg_enc_reply_head msg_enc_reply_head;
    s_msg_enc_reply_data msg_enc_reply_data;
} s_msg_enc_reply;

//note msg
typedef struct {
    uint8_t sync_word[2];
    uint8_t cmd;
    uint8_t size[2];  // high eight bits
} s_msg_note_head;

typedef struct {
    uint8_t nid;    // note id
    uint8_t checksum;
} s_msg_note_data;
/* module -> host note end */

typedef struct {
    s_msg_note_head note_head;
    s_msg_note_data note_data;
} s_msg_note;

// a general message adapter
typedef struct {
    uint8_t mid;       // the message id
    uint8_t size_heb;  // high eight bits
    uint8_t size_leb;  // low eight bits
    uint8_t data[0];
} s_msg;

typedef struct {
    int16_t state; // corresponding to FACE_STATE_*

    // position
    int16_t left;  // in pixel
    int16_t top;
    int16_t right;
    int16_t bottom;

    // pose
    int16_t yaw;   // up and down in vertical orientation
    int16_t pitch; // right or left turned in horizontal orientation
    int16_t roll;  // slope
} s_note_data_face;

// enroll user
typedef struct {
    uint8_t admin; // the user will be set to admin
    uint8_t user_name[USER_NAME_SIZE];
    s_face_dir face_direction;
    uint8_t timeout; // timeout, unit second default 10s
} s_msg_enroll_data;

// resign id enroll user 
typedef struct {
    uint8_t admin; // the user will be set to admin
    uint8_t user_name[USER_NAME_SIZE];
    s_face_dir face_direction;
    uint8_t timeout; // timeout, unit second default 10s
    uint16_t user_id;
} s_msg_enroll_cover_data;

// verify
typedef struct {
    uint8_t pd_rightaway; // power down right away after verifying
    uint8_t timeout; // timeout, unit second, default 10s
} s_msg_verify_data;

// delete user
typedef struct {
    uint8_t user_id_heb; // high eight bits of user_id to be deleted
    uint8_t user_id_leb; // low eight bits pf user_id to be deleted
} s_msg_deluser_data;

// get user info
typedef struct {
    uint8_t user_id_heb; // high eight bits of user_id to get info
    uint8_t user_id_leb; // low eight bits of user_id to get info
} s_msg_getuserinfo_data;

// del user id rang
typedef struct {
    uint16_t user_id_from; // high eight bits of user_id to get info
    uint16_t user_id_to; // low eight bits of user_id to get info
} s_msg_deluser_rang_data;

// start ota data MID_START_OTA
typedef struct {
    uint8_t v_primary;   // primary version number
    uint8_t v_secondary; // secondary version number
    uint8_t v_revision;  // revision number
} s_msg_startota_data;

// ota header MID_OTA_HEADER
typedef struct {
    uint8_t fsize_b[4];  // OTA FW file size int -> [b1, b2, b3, b4]
    uint8_t num_pkt[4];  // number packet to be divided for transferring, int -> [b1, b2, b3, b4]
    uint8_t pkt_size[2]; // raw data size of single packet
    uint8_t md5_sum[32]; // md5 check sum
} s_msg_otaheader_data;

// ota packet MID_OTA_PACKET
typedef struct {
    uint8_t pid[2];   // the packet id
    uint8_t psize[2]; // the size of this package
    uint8_t data[0];  // data 0 start
} s_msg_otapacket_data;

typedef struct { 
 	uint8_t verify_threshold_level; 	// level 0~4, safety from low to high, default 2 
 	uint8_t liveness_threshold_level; 	// level 0~4, safety from low to high, default 2 
} s_msg_algo_threshold_level;


// MID_INIT_ENCRYPTION data
typedef struct {
    uint8_t seed[4]; // random data as a seed
uint8_t mode;    // reserved for selecting encrytion mode
uint8_t crttime[4];
} s_msg_init_encryption_data;

// demo data
typedef struct {
    uint8_t enable; // enable demo or not
} s_msg_demomode_data;

// snap image data
typedef struct {
    uint8_t image_counts; // number of stored images
    uint8_t start_number; // start number of stored images
} s_msg_snap_image_data;

// get saved image data
typedef struct {
    uint8_t image_number; // number of saved image
} s_msg_get_saved_image_data;

// upload image
typedef struct {
    uint8_t upload_image_offset[4]; // upload image offset, int -> [o1 o2 o3 o4]
    uint8_t upload_image_size[4];   // uploade image size, int -> [s1 s2 s3 s4]
} s_msg_upload_image_data;

// upload logfile
typedef struct {
    uint8_t upload_logfile_offset[4]; // upload logfile offset, int -> [o1 o2 o3 o4]
    uint8_t upload_logfile_size[4];   // uploade logfile size, int -> [s1 s2 s3 s4]
} s_msg_upload_logfile_data;

// DDR test
typedef struct {
    uint8_t ddr_test_counts; // number of DDR testing
} s_msg_ddr_test_data;

/* message reply data definitions */
typedef struct {
    uint8_t user_id_heb;
    uint8_t user_id_leb;
    uint8_t user_name[USER_NAME_SIZE];
    uint8_t admin;
    uint8_t unlockStatus;
} s_msg_reply_verify_data;

typedef struct {
    uint8_t user_id_heb;
    uint8_t user_id_leb;
    uint8_t face_direction;
} s_msg_reply_enroll_data;

typedef struct {
    uint8_t status;
} s_msg_reply_getstatus_data;

typedef struct {
    uint8_t version_info[VERSION_INFO_BUFFER_SIZE];
} s_msg_reply_version_data;

typedef struct {
    uint8_t user_id_heb;
    uint8_t user_id_leb;
    uint8_t user_name[USER_NAME_SIZE];
    uint8_t admin;
} s_msg_reply_getuserinfo_data;

typedef struct {
    uint8_t user_counts;      // number of enrolled users
    uint8_t users_id[MAX_USER_COUNTS*2];   //use 2 bytes to save a user ID and save high eight bits firstly
} s_msg_reply_all_userid_data;

typedef struct {
    uint8_t time_heb;      // high eight bits of factory test time
    uint8_t time_leb;      // low eight bits of facetory test time
} s_msg_reply_factory_test_data;

// MID_INIT_ENCRYPTION reply
typedef struct {
    uint8_t device_id[20]; // the unique ID of this device, string type
} s_msg_reply_init_encryption_data;

// REPLY MID_GET_OTA_STATUS
typedef struct {
    uint8_t ota_status; // current ota status
    uint8_t next_pid_e[2]; // expected next pid, [b0,b1]
} s_msg_reply_getotastatus_data;

typedef struct {
    uint8_t image_size[4];   // image size int -> [s1, s2, s3, s4]
} s_msg_reply_get_saved_image_data;

typedef struct {
    uint8_t  ota_result;//0 :is sucess; 1: is faile;
} s_note_ota_result;

typedef struct {
uint8_t baudrate_index;//1: is 115200 (115200*1); 2 is 230400 (115200*2); 3 is 460800 (115200*4); 4 is 1500000
} s_msg_config_baudrate;

typedef struct {
    uint8_t enc_key_number[16];   //
} s_msg_enc_key_number_data;

typedef struct {
    uint8_t SyncWord[2];
    uint8_t MsgID;
    uint8_t Size[2];
    uint8_t Data[0];  
	//uint8_t ParityCheck;
} msg_pack_t;

typedef struct {
    uint8_t enc_release_key[16];   
} s_msg_enc_release_key_data;

typedef struct {
    uint8_t enc_debug_key[16];   
} s_msg_enc_debug_key_data;

typedef struct {
    uint8_t MsgID;
    uint8_t Size[2];
    uint8_t Data[DATA_RECVED_MAX_NUM];  
} msg_pack_clear_t;

typedef struct {
    uint8_t MsgID;
    uint8_t Size[2];
    uint8_t mid;
    uint8_t result;
    s_msg_reply_verify_data data;
 } s_msg_verify_reply_t;

typedef struct {
   uint8_t MsgID;
    uint8_t Size[2]; 
    uint8_t mid;
    uint8_t result;    
    s_msg_reply_enroll_data data;    
} s_msg_enroll_reply_t;


typedef struct {
   uint8_t MsgID;
    uint8_t Size[2]; 
    uint8_t mid;
    s_note_data_face face;
} s_msg_note_face_t;    

typedef struct {
   uint8_t MsgID;
    uint8_t Size[2]; 
    uint8_t mid;
    uint8_t result; 
    s_msg_reply_version_data data;
} s_msg_version_t;

typedef struct {
   uint8_t MsgID;
    uint8_t Size[2]; 
    uint8_t mid;
    uint8_t result; 
    s_msg_reply_all_userid_data data;
} s_msg_userid_reply_t;

typedef struct {
    uint8_t MsgID;
    uint8_t Size[2]; 
    uint8_t mid;
    uint8_t result; 
    s_msg_reply_getuserinfo_data data;
} s_msg_getuserinfo_t;

/*
#define GET_REQ_CMD(req)    ((((req_pack_head_t*)req)->cmd))
#define GET_REQ_LEN(req)    (((((req_pack_head_t*)req)->len[0]) << 24) \
                           + ((((req_pack_head_t*)req)->len[1]) << 16) \
                           + ((((req_pack_head_t*)req)->len[2]) << 8) \
                           + (((req_pack_head_t*)req)->len[3]))
                           
#define GET_REQ_ID(req)     (((((req_pack_head_t*)req)->id[0])<<24)+((((req_pack_head_t*)req)->id[1])<<16) \
                           + ((((req_pack_head_t*)req)->id[2]) << 8) + (((req_pack_head_t*)req)->id[3]))
                           
#define GET_REQ_CH(req)    (((((req_pack_head_t*)req)->dat[0]) << 8) + (((req_pack_head_t*)req)->dat[1]))

#define GET_REQ_H(req)     (((((req_pack_head_t*)req)->dat[2])<<8) + (((req_pack_head_t*)req)->dat[3]))

#define GET_REQ_W(req)     (((((req_pack_head_t*)req)->dat[4])<<8)+(((req_pack_head_t*)req)->dat[5]))

                               


#define GET_RESP_CMD(resp)  	((((resp_pack_head_t*)resp)->cmd))
#define GET_RESP_RESULT(resp) 	((((resp_pack_head_t*)resp)->result))
#define GET_RESP_LEN(resp)  	(sizeof(resp_pack_head_t) + ((((resp_pack_head_t*)resp)->len[0]) << 24) \
                               + ((((resp_pack_head_t*)resp)->len[1]) << 16) + ((((resp_pack_head_t*)resp)->len[2]) << 8) \
                               + (((resp_pack_head_t*)resp)->len[3]))
*/



void store_le_uint32(uint8_t *addr, uint32_t value);
void store_le_uint16(uint8_t *addr, uint16_t value);
void dump_le_uint32(uint8_t *addr, uint32_t *value);
uint32_t dump_uint32(uint8_t *addr);
void dump_le_uint16(uint8_t *addr, uint16_t *value);
uint8_t get_check_parity(uint8_t *buf, uint32_t size);
uint8_t get_check_sum(uint8_t *buf, uint32_t size);
void pack_head(uint8_t cmd, uint32_t id, uint32_t payload_len, uint8_t *packet);

//int send_packet(uint8_t *packet, uint32_t len);
//int get_result(uint8_t *send, uint8_t *recv);


int m2h_msg_send(uart_dev_t *uart, uint8_t msgid, uint32_t size, uint8_t *data);
int h2m_msg_recv(uart_dev_t *uart, uint8_t *inbuf, int *rece_size);

int m2h_register_from_uart_ack(uart_dev_t *uart,uint32_t result,uint32_t id);

#endif
